package pl.vm.domain.simulator;

import pl.vm.domain.Player;
import pl.vm.domain.PlayerPosition;
import pl.vm.domain.Squad;
import pl.vm.domain.SquadComposition;
import pl.vm.domain.Statistics;
import pl.vm.domain.VirtualTeam;
import pl.vm.domain.interfaces.Round;

public class SimplePointsCalculator implements PointsCalculator {

	@Override
	public double calculatePlayerPoints(Statistics stats, Player player) {
		PlayerPosition position = player.getPosition();
		double points = 0;
		if (stats.getPlayedSets() == 0) {
			return 0;
		}
		if (position != PlayerPosition.COACH) {
			points = calculateGeneral(stats);
		}
		switch (position) {
		case BLOCKER:
			points += calculateBlocker(stats);
			break;
		case COACH:
			points += calculateCoach(stats);
			break;
		case LIBERO:
			points += calculateLibero(stats);
			break;
		case OPPOSITE:
			points += calculateOpposite(stats);
			break;
		case RECEIVER:
			points += calculateReceiver(stats);
			break;
		case SETTER:
			points += calculateSetter(stats);
			break;
		}
		if (stats.isMvp()) {
			points *= Modifiers.MVP_MODIFIER;
		}
		return points;
	}

	private double calculateSetter(Statistics stats) {
		double points = 0;
		switch (stats.getScore()) {
		case _0_3:
			points += Modifiers.SETTER_TEAM_0_3_MODIFIER;
			break;
		case _1_3:
			points += Modifiers.SETTER_TEAM_1_3_MODIFIER;
			break;
		case _2_3:
			points += Modifiers.SETTER_TEAM_2_3_MODIFIER;
			break;
		case _3_0:
			points += Modifiers.SETTER_TEAM_3_0_MODIFIER;
			break;
		case _3_1:
			points += Modifiers.SETTER_TEAM_3_1_MODIFIER;
			break;
		case _3_2:
			points += Modifiers.SETTER_TEAM_3_2_MODIFIER;
		}
		if (stats.getPlayedSets() > 1) {
			int teamAttack = stats.getTeamAttackPercentage();
			if (teamAttack <= Modifiers.TEAM_EFFECTIVE_LEVEL_1) {
				points += Modifiers.TEAM_EFFECTIVE_LEVEL_1_MODIFIER;
			} else if (teamAttack <= Modifiers.TEAM_EFFECTIVE_LEVEL_2
					&& teamAttack > Modifiers.TEAM_EFFECTIVE_LEVEL_1) {
				points += Modifiers.TEAM_EFFECTIVE_LEVEL_2_MODIFIER;
			} else if (teamAttack <= Modifiers.TEAM_EFFECTIVE_LEVEL_3
					&& teamAttack > Modifiers.TEAM_EFFECTIVE_LEVEL_2) {
				points += Modifiers.TEAM_EFFECTIVE_LEVEL_3_MODIFIER;
			} else if (teamAttack <= Modifiers.TEAM_EFFECTIVE_LEVEL_4
					&& teamAttack > Modifiers.TEAM_EFFECTIVE_LEVEL_3) {
				points += Modifiers.TEAM_EFFECTIVE_LEVEL_4_MODIFIER;
			} else if (teamAttack <= Modifiers.TEAM_EFFECTIVE_LEVEL_5
					&& teamAttack > Modifiers.TEAM_EFFECTIVE_LEVEL_4) {
				points += Modifiers.TEAM_EFFECTIVE_LEVEL_5_MODIFIER;
			} else if (teamAttack <= Modifiers.TEAM_EFFECTIVE_LEVEL_6
					&& teamAttack > Modifiers.TEAM_EFFECTIVE_LEVEL_5) {
				points += Modifiers.TEAM_EFFECTIVE_LEVEL_6_MODIFIER;
			} else if (teamAttack <= Modifiers.TEAM_EFFECTIVE_LEVEL_7
					&& teamAttack > Modifiers.TEAM_EFFECTIVE_LEVEL_6) {
				points += Modifiers.TEAM_EFFECTIVE_LEVEL_7_MODIFIER;
			} else if (teamAttack <= Modifiers.TEAM_EFFECTIVE_LEVEL_8
					&& teamAttack > Modifiers.TEAM_EFFECTIVE_LEVEL_7) {
				points += Modifiers.TEAM_EFFECTIVE_LEVEL_8_MODIFIER;
			} else if (teamAttack <= Modifiers.TEAM_EFFECTIVE_LEVEL_9
					&& teamAttack > Modifiers.TEAM_EFFECTIVE_LEVEL_8) {
				points += Modifiers.TEAM_EFFECTIVE_LEVEL_9_MODIFIER;
			} else if (teamAttack <= Modifiers.TEAM_EFFECTIVE_LEVEL_10
					&& teamAttack > Modifiers.TEAM_EFFECTIVE_LEVEL_9) {
				points += Modifiers.TEAM_EFFECTIVE_LEVEL_10_MODIFIER;
			}
		}
		return points;
	}

	private double calculateReceiver(Statistics stats) {
		double points = stats.getLostPointInReception()
				* Modifiers.RECEIVER_POINTS_LOST_IN_RECEPTION_MODIFIER;
		if (stats.getNumberOfReception() >= Modifiers.RECEIVER_MINIMUM_NR_OF_RECEPTIONS) {
			int receptionPercentage = stats.getPositiveReception();
			if (receptionPercentage <= Modifiers.RECEIVER_EFFECTIVE_LEVEL_1) {
				points += Modifiers.RECEIVER_EFFECTIVE_LEVEL_1_MODIFIER;
			} else if (receptionPercentage <= Modifiers.RECEIVER_EFFECTIVE_LEVEL_2
					&& receptionPercentage > Modifiers.RECEIVER_EFFECTIVE_LEVEL_1) {
				points += Modifiers.RECEIVER_EFFECTIVE_LEVEL_2_MODIFIER;
			} else if (receptionPercentage <= Modifiers.RECEIVER_EFFECTIVE_LEVEL_3
					&& receptionPercentage > Modifiers.RECEIVER_EFFECTIVE_LEVEL_2) {
				points += Modifiers.RECEIVER_EFFECTIVE_LEVEL_3_MODIFIER;
			} else if (receptionPercentage <= Modifiers.RECEIVER_EFFECTIVE_LEVEL_4
					&& receptionPercentage > Modifiers.RECEIVER_EFFECTIVE_LEVEL_3) {
				points += Modifiers.RECEIVER_EFFECTIVE_LEVEL_4_MODIFIER;
			} else if (receptionPercentage <= Modifiers.RECEIVER_EFFECTIVE_LEVEL_5
					&& receptionPercentage > Modifiers.RECEIVER_EFFECTIVE_LEVEL_4) {
				points += Modifiers.RECEIVER_EFFECTIVE_LEVEL_5_MODIFIER;
			} else if (receptionPercentage <= Modifiers.RECEIVER_EFFECTIVE_LEVEL_6
					&& receptionPercentage > Modifiers.RECEIVER_EFFECTIVE_LEVEL_5) {
				points += Modifiers.RECEIVER_EFFECTIVE_LEVEL_6_MODIFIER;
			} else if (receptionPercentage <= Modifiers.RECEIVER_EFFECTIVE_LEVEL_7
					&& receptionPercentage > Modifiers.RECEIVER_EFFECTIVE_LEVEL_6) {
				points += Modifiers.RECEIVER_EFFECTIVE_LEVEL_7_MODIFIER;
			} else if (receptionPercentage <= Modifiers.RECEIVER_EFFECTIVE_LEVEL_8
					&& receptionPercentage > Modifiers.RECEIVER_EFFECTIVE_LEVEL_7) {
				points += Modifiers.RECEIVER_EFFECTIVE_LEVEL_8_MODIFIER;
			} else if (receptionPercentage <= Modifiers.RECEIVER_EFFECTIVE_LEVEL_9
					&& receptionPercentage > Modifiers.RECEIVER_EFFECTIVE_LEVEL_8) {
				points += Modifiers.RECEIVER_EFFECTIVE_LEVEL_9_MODIFIER;
			} else if (receptionPercentage <= Modifiers.RECEIVER_EFFECTIVE_LEVEL_10
					&& receptionPercentage > Modifiers.RECEIVER_EFFECTIVE_LEVEL_9) {
				points += Modifiers.RECEIVER_EFFECTIVE_LEVEL_10_MODIFIER;
			}
		}
		return points;
	}

	private double calculateOpposite(Statistics stats) {
		double points = stats.getBlockedAttacks() * Modifiers.OPPOSITE_BLOCKED_ATTACKS_MODIFIER;
		if (stats.getNumberOfAttacks() >= Modifiers.OPPOSITE_NR_OF_MINIMUM_ATTACKS) {
			int attackPercentage = stats.getAttackPercentage();
			if (attackPercentage <= Modifiers.OPPOSITE_EFFECTIVE_LEVEL_1) {
				points += Modifiers.OPPOSITE_EFFECTIVE_LEVEL_1_MODIFIER;
			} else if (attackPercentage <= Modifiers.OPPOSITE_EFFECTIVE_LEVEL_2
					&& attackPercentage > Modifiers.OPPOSITE_EFFECTIVE_LEVEL_1) {
				points += Modifiers.OPPOSITE_EFFECTIVE_LEVEL_2_MODIFIER;
			} else if (attackPercentage <= Modifiers.OPPOSITE_EFFECTIVE_LEVEL_3
					&& attackPercentage > Modifiers.OPPOSITE_EFFECTIVE_LEVEL_2) {
				points += Modifiers.OPPOSITE_EFFECTIVE_LEVEL_3_MODIFIER;
			} else if (attackPercentage <= Modifiers.OPPOSITE_EFFECTIVE_LEVEL_4
					&& attackPercentage > Modifiers.OPPOSITE_EFFECTIVE_LEVEL_3) {
				points += Modifiers.OPPOSITE_EFFECTIVE_LEVEL_4_MODIFIER;
			} else if (attackPercentage <= Modifiers.OPPOSITE_EFFECTIVE_LEVEL_5
					&& attackPercentage > Modifiers.OPPOSITE_EFFECTIVE_LEVEL_4) {
				points += Modifiers.OPPOSITE_EFFECTIVE_LEVEL_5_MODIFIER;
			} else if (attackPercentage <= Modifiers.OPPOSITE_EFFECTIVE_LEVEL_6
					&& attackPercentage > Modifiers.OPPOSITE_EFFECTIVE_LEVEL_5) {
				points += Modifiers.OPPOSITE_EFFECTIVE_LEVEL_6_MODIFIER;
			} else if (attackPercentage <= Modifiers.OPPOSITE_EFFECTIVE_LEVEL_7
					&& attackPercentage > Modifiers.OPPOSITE_EFFECTIVE_LEVEL_6) {
				points += Modifiers.OPPOSITE_EFFECTIVE_LEVEL_7_MODIFIER;
			} else if (attackPercentage <= Modifiers.OPPOSITE_EFFECTIVE_LEVEL_8
					&& attackPercentage > Modifiers.OPPOSITE_EFFECTIVE_LEVEL_7) {
				points += Modifiers.OPPOSITE_EFFECTIVE_LEVEL_8_MODIFIER;
			} else if (attackPercentage <= Modifiers.OPPOSITE_EFFECTIVE_LEVEL_9
					&& attackPercentage > Modifiers.OPPOSITE_EFFECTIVE_LEVEL_8) {
				points += Modifiers.OPPOSITE_EFFECTIVE_LEVEL_9_MODIFIER;
			} else if (attackPercentage <= Modifiers.OPPOSITE_EFFECTIVE_LEVEL_10
					&& attackPercentage > Modifiers.OPPOSITE_EFFECTIVE_LEVEL_9) {
				points += Modifiers.OPPOSITE_EFFECTIVE_LEVEL_10_MODIFIER;
			}
		}
		return points;
	}

	private double calculateLibero(Statistics stats) {
		double points = 0;
		int opponentAttack = stats.getOpponentTeamAttackPercentage();
		if (opponentAttack <= Modifiers.OPPONENT_TEAM_EFFECTIVE_LEVEL_1) {
			points += Modifiers.LIBERO_OPP_TEAM_EFFECITIVE_LEVEL_1_MODIFIER;
		} else if (opponentAttack <= Modifiers.OPPONENT_TEAM_EFFECTIVE_LEVEL_2
				&& opponentAttack > Modifiers.OPPONENT_TEAM_EFFECTIVE_LEVEL_1) {
			points += Modifiers.LIBERO_OPP_TEAM_EFFECITIVE_LEVEL_2_MODIFIER;
		} else if (opponentAttack <= Modifiers.OPPONENT_TEAM_EFFECTIVE_LEVEL_3
				&& opponentAttack > Modifiers.OPPONENT_TEAM_EFFECTIVE_LEVEL_2) {
			points += Modifiers.LIBERO_OPP_TEAM_EFFECITIVE_LEVEL_3_MODIFIER;
		} else if (opponentAttack <= Modifiers.OPPONENT_TEAM_EFFECTIVE_LEVEL_4
				&& opponentAttack > Modifiers.OPPONENT_TEAM_EFFECTIVE_LEVEL_3) {
			points += Modifiers.LIBERO_OPP_TEAM_EFFECITIVE_LEVEL_4_MODIFIER;
		} else if (opponentAttack <= Modifiers.OPPONENT_TEAM_EFFECTIVE_LEVEL_5
				&& opponentAttack > Modifiers.OPPONENT_TEAM_EFFECTIVE_LEVEL_4) {
			points += Modifiers.LIBERO_OPP_TEAM_EFFECITIVE_LEVEL_5_MODIFIER;
		} else if (opponentAttack <= Modifiers.OPPONENT_TEAM_EFFECTIVE_LEVEL_6
				&& opponentAttack > Modifiers.OPPONENT_TEAM_EFFECTIVE_LEVEL_5) {
			points += Modifiers.LIBERO_OPP_TEAM_EFFECITIVE_LEVEL_6_MODIFIER;
		} else if (opponentAttack <= Modifiers.OPPONENT_TEAM_EFFECTIVE_LEVEL_7
				&& opponentAttack > Modifiers.OPPONENT_TEAM_EFFECTIVE_LEVEL_6) {
			points += Modifiers.LIBERO_OPP_TEAM_EFFECITIVE_LEVEL_7_MODIFIER;
		} else if (opponentAttack <= Modifiers.OPPONENT_TEAM_EFFECTIVE_LEVEL_8
				&& opponentAttack > Modifiers.OPPONENT_TEAM_EFFECTIVE_LEVEL_7) {
			points += Modifiers.LIBERO_OPP_TEAM_EFFECITIVE_LEVEL_8_MODIFIER;
		} else if (opponentAttack <= Modifiers.OPPONENT_TEAM_EFFECTIVE_LEVEL_9
				&& opponentAttack > Modifiers.OPPONENT_TEAM_EFFECTIVE_LEVEL_8) {
			points += Modifiers.LIBERO_OPP_TEAM_EFFECITIVE_LEVEL_9_MODIFIER;
		} else if (opponentAttack <= Modifiers.OPPONENT_TEAM_EFFECTIVE_LEVEL_10
				&& opponentAttack > Modifiers.OPPONENT_TEAM_EFFECTIVE_LEVEL_9) {
			points += Modifiers.LIBERO_OPP_TEAM_EFFECITIVE_LEVEL_10_MODIFIER;
		}
		int reception = stats.getPositiveReception();
		if (reception <= Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_1) {
			points += Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_1_MODIFIER;
		} else if (reception <= Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_2
				&& reception > Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_1) {
			points += Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_2_MODIFIER;
		} else if (reception <= Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_3
				&& reception > Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_2) {
			points += Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_3_MODIFIER;
		} else if (reception <= Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_4
				&& reception > Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_3) {
			points += Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_4_MODIFIER;
		} else if (reception <= Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_5
				&& reception > Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_4) {
			points += Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_5_MODIFIER;
		} else if (reception <= Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_6
				&& reception > Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_5) {
			points += Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_6_MODIFIER;
		} else if (reception <= Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_7
				&& reception > Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_6) {
			points += Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_7_MODIFIER;
		} else if (reception <= Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_8
				&& reception > Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_7) {
			points += Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_8_MODIFIER;
		} else if (reception <= Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_9
				&& reception > Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_8) {
			points += Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_9_MODIFIER;
		} else if (reception <= Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_10
				&& reception > Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_9) {
			points += Modifiers.LIBERO_RECEPTION_EFFECTIVE_LEVEL_10_MODIFIER;
		}
		return points;
	}

	private double calculateCoach(Statistics stats) {
		double points = 0;
		switch (stats.getScore()) {
		case _0_3:
			points += Modifiers.COACH_TEAM_0_3_MODIFIER;
			break;
		case _1_3:
			points += Modifiers.COACH_TEAM_1_3_MODIFIER;
			break;
		case _2_3:
			points += Modifiers.COACH_TEAM_2_3_MODIFIER;
			break;
		case _3_0:
			points += Modifiers.COACH_TEAM_3_0_MODIFIER;
			break;
		case _3_1:
			points += Modifiers.COACH_TEAM_3_1_MODIFIER;
			break;
		case _3_2:
			points += Modifiers.COACH_TEAM_3_2_MODIFIER;
			break;
		}
		return points;
	}

	private double calculateBlocker(Statistics stats) {
		double points = stats.getBlockedAttacks() * Modifiers.BLOCKER_BLOCKED_ATTACKS_MODIFIER;
		if (stats.getBlockedAttacks() >= Modifiers.BLOCKER_MINIMUM_ATTACKS_MODIFIER) {
			int attackPercentage = stats.getAttackPercentage();
			if (attackPercentage <= Modifiers.BLOCKER_EFFECTIVE_LEVEL_1) {
				points += Modifiers.BLOCKER_EFFECTIVE_LEVEL_1_MODIFIER;
			} else if (attackPercentage <= Modifiers.BLOCKER_EFFECTIVE_LEVEL_2
					&& attackPercentage > Modifiers.BLOCKER_EFFECTIVE_LEVEL_1) {
				points += Modifiers.BLOCKER_EFFECTIVE_LEVEL_2_MODIFIER;
			} else if (attackPercentage <= Modifiers.BLOCKER_EFFECTIVE_LEVEL_3
					&& attackPercentage > Modifiers.BLOCKER_EFFECTIVE_LEVEL_2) {
				points += Modifiers.BLOCKER_EFFECTIVE_LEVEL_3_MODIFIER;
			} else if (attackPercentage <= Modifiers.BLOCKER_EFFECTIVE_LEVEL_4
					&& attackPercentage > Modifiers.BLOCKER_EFFECTIVE_LEVEL_3) {
				points += Modifiers.BLOCKER_EFFECTIVE_LEVEL_4_MODIFIER;
			} else if (attackPercentage <= Modifiers.BLOCKER_EFFECTIVE_LEVEL_5
					&& attackPercentage > Modifiers.BLOCKER_EFFECTIVE_LEVEL_4) {
				points += Modifiers.BLOCKER_EFFECTIVE_LEVEL_5_MODIFIER;
			} else if (attackPercentage <= Modifiers.BLOCKER_EFFECTIVE_LEVEL_6
					&& attackPercentage > Modifiers.BLOCKER_EFFECTIVE_LEVEL_5) {
				points += Modifiers.BLOCKER_EFFECTIVE_LEVEL_6_MODIFIER;
			} else if (attackPercentage <= Modifiers.BLOCKER_EFFECTIVE_LEVEL_7
					&& attackPercentage > Modifiers.BLOCKER_EFFECTIVE_LEVEL_6) {
				points += Modifiers.BLOCKER_EFFECTIVE_LEVEL_7_MODIFIER;
			} else if (attackPercentage <= Modifiers.BLOCKER_EFFECTIVE_LEVEL_8
					&& attackPercentage > Modifiers.BLOCKER_EFFECTIVE_LEVEL_7) {
				points += Modifiers.BLOCKER_EFFECTIVE_LEVEL_8_MODIFIER;
			} else if (attackPercentage <= Modifiers.BLOCKER_EFFECTIVE_LEVEL_9
					&& attackPercentage > Modifiers.BLOCKER_EFFECTIVE_LEVEL_8) {
				points += Modifiers.BLOCKER_EFFECTIVE_LEVEL_9_MODIFIER;
			} else if (attackPercentage <= Modifiers.BLOCKER_EFFECTIVE_LEVEL_10
					&& attackPercentage > Modifiers.BLOCKER_EFFECTIVE_LEVEL_9) {
				points += Modifiers.BLOCKER_EFFECTIVE_LEVEL_10_MODIFIER;
			}
		}
		return points;
	}

	private double calculateGeneral(Statistics stats) {
		double points = stats.getAttackPoints() * Modifiers.GENERAL_ATTACK_POINTS_MODIFIER
				+ stats.getBlockPoints() * Modifiers.GENERAL_BLOCK_POINTS_MODIFIER
				+ stats.getServePoints() * Modifiers.GENERAL_SERVE_POINTS_MODIFIER;
		if (stats.isStartFromBegining()) {
			points += Modifiers.GENERAL_STARTING_MODIFIER;
		}
		return points;
	}

	@Override
	public double calculateTeamPointsInRound(VirtualTeam team, Round round) {
		double teamPoints = 0;
		Squad squad = team.getTeamSquad();
		SquadComposition mainSquad = squad.getMainSquad();
		for (Player player : mainSquad) {
			double points = round.getPointsForPlayer(player);
			if (player == team.getCaptain()) {
				teamPoints += points * 2;
			} else {
				teamPoints += points;
			}
		}
		teamPoints += round.getPointsForPlayer(squad.getCoach());
		return teamPoints;
	}
}
